package cn.demoncat.util.lang.entity;

import java.io.IOException;

import cn.demoncat.util.lang.StringUtil;

/**
 * 读取行信息回调
 * 
 * 1、子类实现 protected readXxxImpl方法，来实际读取和处理Info/Warn/Error消息
 * 
 * 2、调用：主动读取时，调用readXxxImpl，不用处理异常，也不会判断标记；被动读取时调用readXxx，发现标记时抛异常来通知停止读取
 * 
 * 3、readXxx方法在读取到READ_FINISH或status=false时，会抛出LineReadFinishException
 * 
 * 4、停止读取：1 设置和判断status=false来在外部停止读取；2 设置status=false后捕捉LineReadFinishException来停止读取；3 READ_FINISH让读取并捕捉LineReadFinishException来停止读取
 *   
 * @author 延晓磊
 *
 * @since 2019年6月13日
 */
public abstract class LineReadCallback {
	
	/**
	 * 读取完成退出标记
	 */
	public static final String READ_FINISH = "READ_FINISH_EXIT"; 
	
	/**
	 * 开关
	 */
	private Boolean status = true;
	/**
	 * 是否有info
	 */
	private Boolean hasInfo = false;
	/**
	 * 是否有error
	 * 
	 * 注：因为Shell命令有时会把正确数据通过错误流输出来表达警示，所以不能通过是否有错误消息来校验
	 */
	private Boolean hasError = false;
	/**
	 * 是否有warn
	 */
	private Boolean hasWarn = false;
	
	/**
	 * 读取正常数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 * @throws LineReadFinishException 读取到完成标记
	 *
	 * @since 2019年6月13日
	 */
	public final void read(String line) throws LineReadFinishException {
		line = StringUtil.toEmpty(line);
		if (status) {
			// 停止标记
			if (line.contains(READ_FINISH)) {
				status = false;
				throw LineReadFinishException.INSTANCE;
			}
			// 读取过
			hasInfo = true;
			// 执行读取
			readImpl(line);
		}else {
			// 停止读取
			throw LineReadFinishException.INSTANCE;
		}
	}
	
	/**
	 * 读取错误数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 * @throws LineReadFinishException 读取到完成标记
	 *
	 * @since 2019年6月13日
	 */
	public final void readError(String line) throws LineReadFinishException {
		line = StringUtil.toEmpty(line);
		if (status) {
			// 停止标记
			if (line.contains(READ_FINISH)) {
				status = false;
				throw LineReadFinishException.INSTANCE;
			}
			// 读取过
			hasError = true;
			// 执行读取
			readErrorImpl(line);
		}else {
			// 停止读取
			throw LineReadFinishException.INSTANCE;
		}
	}
	
	/**
	 * 读取警告数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 * @throws LineReadFinishException 读取到完成标记
	 *
	 * @since 2019年6月13日
	 */
	public final void readWarn(String line) throws LineReadFinishException {
		line = StringUtil.toEmpty(line);
		if (status) {
			// 停止标记
			if (line.contains(READ_FINISH)) {
				status = false;
				throw LineReadFinishException.INSTANCE;
			}
			// 读取过
			hasWarn = true;
			// 执行读取
			readWarnImpl(line);
		}else {
			// 停止读取
			throw LineReadFinishException.INSTANCE;
		}
	}

	/**
	 * 读取完成 
	 * 
	 * 场景：输出目标将被其它LineReadCallback用tail读取时，使用READ_FINISH标记通知完成
	 * 
	 * 注意：默认在Status=true时，调用readImpl输出。如果readImpl未实现或对line有处理，应重新实现
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年7月5日
	 */
	public void readFinish() {
		if (status) {
			readImpl(READ_FINISH);
		}
	}
	
	/**
	 * 读取正常数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年6月13日
	 */
	public void readImpl(String line) {
		 // 读取正常数据
	}
	
	/**
	 * 读取错误数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年6月13日
	 */
	public void readErrorImpl(String line){
		 // 读取错误消息
	}
	
	/**
	 * 读取警告数据
	 * 
	 * @param line
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年6月13日
	 */
	public void readWarnImpl(String line) {
		// 读取警告数据
	}
	
	/**
	 * 开关
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年7月1日
	 */
	public Boolean getStatus() {
		return status;
	}
	
	/**
	 * 开关
	 * 
	 * @param status
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年7月1日
	 */
	public void setStatus(Boolean status) {
		this.status = status;
	}

	public Boolean getHasInfo() {
		return hasInfo;
	}

	public void setHasInfo(Boolean hasInfo) {
		this.hasInfo = hasInfo;
	}

	public Boolean getHasError() {
		return hasError;
	}

	public void setHasError(Boolean hasError) {
		this.hasError = hasError;
	}

	public Boolean getHasWarn() {
		return hasWarn;
	}

	public void setHasWarn(Boolean hasWarn) {
		this.hasWarn = hasWarn;
	}
	
	/**
	 * 读取完成的异常
	 * 
	 * 说明：本异常用于通知停止读取（退出方法），并不是发生错误
	 * 
	 * 示例：…… } catch (LineReadFinishException e) { // 停止读取 } ……
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年7月5日
	 */
	public static class LineReadFinishException extends IOException{
 
		private static final long serialVersionUID = 498849053548646022L;
		
		public static final LineReadFinishException INSTANCE = new LineReadFinishException("行数据读取完成");
		
		public LineReadFinishException() {
			super();
		}
		
		public LineReadFinishException(String msg) {
			super(msg);
		}
	}
	
}
